﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Threading;
using System.IO;

namespace ClientPerformance
{

    public delegate void TrafficDelegate();
    public delegate void TrafficPatternUpdateRecievedDelegate(TrafficPatternInfo info);


    [ServiceBehavior(
      InstanceContextMode = InstanceContextMode.Single,
      ConcurrencyMode = ConcurrencyMode.Reentrant,
      UseSynchronizationContext = false)]
    public class PeerService : IPeerServiceContract
    {
        public DataPacket DefaultPacket;
        public TrafficPatternInfo DefaultPattern;
        public StringBuilder Logger;
        public StringBuilder NeighborListLog;

        private object neighborListLock;
        private List<string> neighborList;


        public event TrafficDelegate StartTrafficRecieved;
        public event TrafficDelegate StopTrafficRecieved;

        public event TrafficPatternUpdateRecievedDelegate TrafficPatternUpdated;

        public PeerService(string nodeName)
        {
            // Create a default packet to send to clients
            DefaultPacket = new DataPacket { SourceName = nodeName };

            Logger = new StringBuilder(1024 * 4000);             // Allocate 4MB  (around 20 minutes at 20 nodes)
            NeighborListLog = new StringBuilder(1024 * 4000);    // Allocate 4MB


            neighborList = new List<string>();
            neighborListLock = new object();
        }

        #region IPeerServiceContract Members

        public void SendTrafficPattern(TrafficPatternInfo pattern)
        {
            try
            {
                DefaultPattern = pattern;

                DefaultPacket.SessionId = pattern.SessionId;
                DefaultPacket.Payload = PayloadFactory.Create(pattern.PacketSize);

                if (TrafficPatternUpdated != null)
                    TrafficPatternUpdated(pattern);
                
            }
            catch (Exception ex) { File.AppendAllText("Errors.txt", string.Format("\nSendTrafficPattern: {0}\n{1}\n\n", ex.Message, ex.StackTrace)); }
        }

        public void SendPacket(DataPacket packet)
        {
            try
            {
                /* Format
                 
                    0         1      2      3        4
                 SessionID  Source  Dest  Arrival  MessageID

                 */
                string log = string.Format("{0}\t{1}\t{2}\t{3}\t{4}",
                    packet.SessionId,
                    packet.SourceName,
                    DefaultPacket.SourceName,
                    DateTime.Now.ToString("hh:mm:ss.fff"),
                    packet.MessageId
                    );

                Logger.AppendLine(log);
            }
            catch (Exception ex) { File.AppendAllText("Errors.txt", string.Format("\nSendPacket: {0}\n{1}\n\n", ex.Message, ex.StackTrace)); }
        }

        public void SendNeighborMessage(NeighborAlertMessage message)
        {
            try
            {
                lock (neighborListLock)
                {
                    neighborList.Add(message.SourceId);
                }
            }
            catch (Exception ex)
            {
                File.AppendAllText("Errors.txt", string.Format("\nSendNeighborMessage: {0}\n{1}\n\n", ex.Message, ex.StackTrace));
            }
        }

        public void StartTraffic()
        {
            try
            {
                if (StartTrafficRecieved != null)
                    StartTrafficRecieved();
            }
            catch (Exception ex) { File.AppendAllText("Errors.txt", string.Format("\nStartTraffic: {0}\n{1}\n\n", ex.Message, ex.StackTrace)); }
        }

        public void StopTraffic()
        {
            try
            {
                if (StopTrafficRecieved != null)
                    StopTrafficRecieved();
            }
            catch (Exception ex) { File.AppendAllText("Errors.txt", string.Format("\nStopTraffic: {0}\n{1}\n\n", ex.Message, ex.StackTrace)); }
        }

        #endregion

        public List<string> GetNeighborListCopy()
        {
            List<string> temp;
            lock (neighborListLock)
            {
                temp = new List<string>(neighborList);
                neighborList = new List<string>();
            }
            return temp;
        }
    }

}
